package com.heima.service.impl;

import cn.hutool.jwt.JWTUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.heima.domain.HhPatient;
import com.heima.domain.HhUsers;
import com.heima.domain.HhUsersAccount;
import com.heima.dto.RegisterDto;
import com.heima.mapper.HhPatientMapper;
import com.heima.mapper.HhUsersAccountMapper;
import com.heima.mapper.HhUsersMapper;
import com.heima.service.IHhUsersService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.heima.vo.LoginOpenIdVo;
import com.heima.vo.RegisterVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 * 小程序用户 服务实现类
 * </p>
 *
 * @author 黑马程序员
 * @since 2023-01-29
 */
@Service
public class HhUsersServiceImpl extends ServiceImpl<HhUsersMapper, HhUsers> implements IHhUsersService {

    @Autowired
    private HhUsersMapper hhUsersMapper;

    @Autowired
    private HhUsersAccountMapper hhUsersAccountMapper;

    @Autowired
    private HhPatientMapper hhPatientMapper;

    @Override
    public LoginOpenIdVo getOpenId(String code) {

        // 1. 入参判断
        // isBlank 代表 变量不存在
        // isEmpty 代表 变量存在，但是值为空
        if (StringUtils.isEmpty(code)) {
            throw new RuntimeException("入参不能为空");
        }

        // 2. 请求微信服务接口
        // 2.1 请求什么接口   GET http://localhost:9090/sns/jscode2session
        // 2.2 用什么请求接口 RestTemplate （SpringBoot自带的一个HTTP请求工具）
        String url = "http://localhost:9090/sns/jscode2session";
        String appid = "wxe6f0c12631e361d0";
        String secret = "6cb71ccff4a8bb85c153ad6ec996855c";
        String grant_type = "authorization_code";

        url += "?appid=" + appid;
        url += "&secret=" + secret;
        url += "&js_code=" + code;
        url += "&grant_type=" + grant_type;

        RestTemplate restTemplate = new RestTemplate();

        // 参数一：请求的网址
        // 参数二：返回值的类型（可以直接用一个实体类来接收接口返回值）
        Map response = restTemplate.getForObject(url, Map.class);
        if (response == null) {
            throw new RuntimeException("微信调用异常");
        }

        // 3. 解析微信接口的返回值
//        Object errcode = response.get("errcode");
        Object openid = response.get("openid");

        // 4. 将opinId返回给前端
        LoginOpenIdVo vo = new LoginOpenIdVo();
        vo.setOpenId((String) openid);

        return vo;
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public RegisterVo register(RegisterDto registerDto) {

        // 1. 入参判断
        if (registerDto == null) {
            throw new RuntimeException("入参不能为空");
        }

        // 2. 检测openId+phone是否存在数据库中
        LambdaQueryWrapper<HhUsers> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(HhUsers::getOpenId, registerDto.getOpenId());
        wrapper.eq(HhUsers::getPhone, registerDto.getPhone());

        HhUsers hhUsers = hhUsersMapper.selectOne(wrapper);

        //用来 给 用户存在 情况下token的payload（载荷，用户信息，map类型）
        Map<String, Object> payload = new HashMap<>();
        // 3. 不存在
        if (hhUsers == null) {
            // 创建新用户(开启事务)
            // 1. hh_users
            HhUsers users = new HhUsers();
            BeanUtils.copyProperties(registerDto, users);
            users.setNickname(registerDto.getNickName());
            users.setAvatar(registerDto.getAvatarUrl());
            int insertResult = hhUsersMapper.insert(users);
            if (insertResult != 1) {
                throw new RuntimeException("用户表插入数据失败");
            }

            // 2. hh_user_account
            HhUsersAccount account = new HhUsersAccount();
            account.setUserId(users.getId());
            account.setBalance(0);
            int insertAccountResult = hhUsersAccountMapper.insert(account);
            if (insertAccountResult != 1) {
                throw new RuntimeException("用户资金账户表插入数据失败");
            }

            // 3. hh_patient
            HhPatient patient = new HhPatient();
            patient.setUserId(users.getId());
            patient.setAddress(registerDto.getCountry() + " " + registerDto.getProvince() + " " + registerDto.getCity());
            patient.setCardNumber("");
            patient.setCardType(0);
            patient.setIsDefault(1);
            patient.setName(registerDto.getNickName());
            patient.setPhone(registerDto.getPhone());
            patient.setTags("本人");
            int insertpatientResult = hhPatientMapper.insert(patient);
            if (insertpatientResult != 1) {
                throw new RuntimeException("就诊人信息插入失败");
            }
            //不存在就创建，然后获取id和openId
            payload.put("id", users.getId());
            payload.put("openId", users.getOpenId());
        } else {
            //存在的情况，就去获取数据库中对应信息的id和openId
            payload.put("id", hhUsers.getId());
            payload.put("openId", hhUsers.getOpenId());
        }
        // 4. 存在
        // 生成token，并且返回给前端

        // JWT -> 生成token
        // token: headers(头部).payload(载荷).signature(签名)
        // headers: 包含加密算法名称
        // payload: 包含用户信息(json字符串)
        // signature: 签名(headers+payloads)

        // 参数一：headers 头文件
        // 参数二：payload 载荷
        // 参数三：key 秘钥


        String token = JWTUtil.createToken(null, payload, "heima".getBytes());

        RegisterVo registerVo = new RegisterVo();
        registerVo.setToken(token);

        return registerVo;
    }


}
